package Api;

import Util.HttpUtil;
import Util.MyKey;
import Util.SimpleXmlParser;
import Util.Tools;

import java.util.HashMap;
import java.util.Map;


/**
 * 对账接口实现类
 * 接口文档: https://open.heepay.com/www/index.html#/openDoc?type=menu&id=2022340
 */
public class PaymentCheck {
    // 接口常量定义
    private static final String API_URL = "https://www.heepay.com/API/Check/PaymentCheck.aspx";
    private static final String VERSION_V2 = "2";
    private static final String VERSION_V3 = "3";

    // 支付类型常量
    public static final int PAY_TYPE_ALL = 0;         // 所有支付
    public static final int PAY_TYPE_MERCHANT = 3;    // 商家余额支付
    public static final int PAY_TYPE_JUNKA = 10;      // 骏卡
    public static final int PAY_TYPE_ONLINE_BANK = 20;// 网银
    public static final int PAY_TYPE_ALIPAY = 22;     // 支付宝
    public static final int PAY_TYPE_WECHAT = 30;     // 微信
    // 可根据需要添加更多支付类型

    private final String agentId;  // 商户编号
    private final String md5Key;   // MD5密钥

    /**
     * 构造方法
     * @param agentId 商户编号
     * @param md5Key MD5密钥
     */
    public PaymentCheck(String agentId, String md5Key) {
        this.agentId = agentId;
        this.md5Key = md5Key;

    }

    /**
     * 默认构造方法，使用配置的商户信息
     */
    public PaymentCheck() {
        this.agentId = "1664502";  // 可移至配置文件
        this.md5Key = MyKey.MD5Key2;
    }

    /**
     * 发送对账请求
     * @param payType 支付类型
     * @param version 接口版本
     * @param beginTime 开始时间(格式: yyyyMMddHHmmss)
     * @param endTime 结束时间(格式: yyyyMMddHHmmss)
     * @param pageIndex 页码
     * @param pageSize 每页条数
     * @return 接口返回结果
     * @throws Exception 异常信息
     */
    public String checkPayment(int payType, String version, String beginTime,
                               String endTime, int pageIndex, int pageSize) throws Exception {
        // 参数校验
        validateParameters(beginTime, endTime, pageIndex, pageSize);

        // 生成签名
        String sign = generateSign(payType, version, beginTime, endTime, pageIndex, pageSize);

        // 构建请求参数
        Map<String, String> parameters = buildParameters(payType, version, beginTime,
                endTime, pageIndex, pageSize, sign);

        // 打印请求参数
        String requestStr = Tools.MaptoStr(parameters);
        System.out.println("发送请求数据：" + requestStr);

        // 发送POST请求
        return HttpUtil.sendPost1(API_URL, parameters);
    }

    /**
     * 参数校验
     */
    private void validateParameters(String beginTime, String endTime, int pageIndex, int pageSize) {
        if (beginTime == null || !beginTime.matches("\\d{14}")) {
            throw new IllegalArgumentException("开始时间格式错误，应为yyyyMMddHHmmss");
        }
        if (endTime == null || !endTime.matches("\\d{14}")) {
            throw new IllegalArgumentException("结束时间格式错误，应为yyyyMMddHHmmss");
        }
        if (beginTime.compareTo(endTime) > 0) {
            throw new IllegalArgumentException("开始时间不能晚于结束时间");
        }
        if (pageIndex < 1) {
            throw new IllegalArgumentException("页码必须大于0");
        }
        if (pageSize < 1 || pageSize > 500) {  // 最大500条
            throw new IllegalArgumentException("每页条数必须在1-500之间");
        }
    }

    /**
     * 生成签名
     */
    private String generateSign(int payType, String version, String beginTime,
                                String endTime, int pageIndex, int pageSize) {
        StringBuilder signSource = new StringBuilder();
        signSource.append("agent_id=").append(agentId)
                .append("&begin_time=").append(beginTime)
                .append("&end_time=").append(endTime)
                .append("&key=").append(md5Key)
                .append("&page_index=").append(pageIndex)
                .append("&page_size=").append(pageSize)
                .append("&pay_type=").append(payType)
                .append("&version=").append(version);

        return Tools.getMD5(signSource.toString().toLowerCase());
    }

    /**
     * 构建请求参数Map
     */
    private Map<String, String> buildParameters(int payType, String version, String beginTime,
                                                String endTime, int pageIndex, int pageSize, String sign) {
        Map<String, String> parameters = new HashMap<>(8);
        parameters.put("version", version);
        parameters.put("pay_type", String.valueOf(payType));
        parameters.put("agent_id", agentId);
        parameters.put("begin_time", beginTime);
        parameters.put("end_time", endTime);
        parameters.put("page_size", String.valueOf(pageSize));
        parameters.put("page_index", String.valueOf(pageIndex));
        parameters.put("sign", sign);
        return parameters;
    }

    /**
     * 解析接口返回结果
     * @param result 接口返回的原始结果
     */
    public void parseResult(String result) {
        if (result == null || result.isEmpty()) {
            System.out.println("接口返回空结果");
            return;
        }

        // 根据实际返回格式解析（JSON/XML），这里仅做示例
        System.out.println("原始响应：" + result);

        /** XML示例
         * <?xml version="1.0" encoding="utf-8"?>
         * <root>
         *     <ret_code>0000</ret_code>
         *     <ret_msg></ret_msg>
         *     <agent_id>1664502</agent_id>
         *     <detail_data>H2010258113173AF,ME20201025121342462686,2020-10-25 12:13:48,2020-10-25 12:13:59,0.01,微信支付,0.0100,2020-10-26</detail_data>
         *     <total_page>1</total_page>
         *     <total_count>1</total_count>
         *     <TotalBillNum>1</TotalBillNum>
         *     <TotalTradeAmt>0.0100</TotalTradeAmt>
         *     <TotalRealAmt>0.0100</TotalRealAmt>
         *     <TotalSettleAmt>0.0000</TotalSettleAmt>
         *     <sign>3a989a672d45f6f806a919351b980081</sign>
         * </root>
         */

        // 解析XML示例
        try {
            // 解析XML
            System.out.println("响应解析结果");
            Map<String, String> resultMap = SimpleXmlParser.toMap(result);

            System.out.println("单据信息: " + resultMap.get("detail_data"));

        } catch (Exception e){
            System.err.println("解析异常：" + e.getMessage());
        }
    }

    public static void main(String[] args) {
        try {
            // 创建实例
            PaymentCheck paymentCheck = new PaymentCheck();

            // 设置请求参数
            int payType = PAY_TYPE_ALL;
            String version = VERSION_V2;
            String beginTime = "20201024235959";
            String endTime = "20201025235959";
            int pageIndex = 1;
            int pageSize = 500;

            // 发送请求
            String result = paymentCheck.checkPayment(payType, version, beginTime,
                    endTime, pageIndex, pageSize);

            // 解析结果
            paymentCheck.parseResult(result);

        } catch (IllegalArgumentException e) {
            System.err.println("参数错误：" + e.getMessage());
        } catch (Exception e) {
            System.err.println("请求异常：" + e.getMessage());
            e.printStackTrace();
        }
    }
}